﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;

namespace LegtionMVVM
{
    internal interface IConverData
    {
        object ToConver( object instance);
    }
    internal class DataConvertor<T, P> : IConverData
    {
        private Func<T, P> ToConverData;
        public DataConvertor(Type tIn, Type tOut)
        {
            string methodName = "To";
            switch (tOut.Name)
            {
                case "Int":
                    methodName += "Int32";
                    break;
                default:
                    methodName += tOut.Name;
                    break;
            }
            MethodInfo method = typeof(Convert).GetMethod(methodName, new Type[] { tIn });
            if(method!=null)
            ToConverData = (Func<T, P>)Delegate.CreateDelegate(typeof(Func<T, P>), method);
        }
        public object ToConver(object instance)
        {
            if (ToConverData != null)
            {
                return ToConverData((T)instance);
            }
            return default(P);
        }
 
    }
    internal static class ConverData
    {
        private static Dictionary<string, IConverData> converCache = new Dictionary<string, IConverData>();

        public static object ToConver(Type tIn, Type tOut, object objIn)
        {
            if (tOut == tIn)
                return objIn;
            if (tOut == typeof(string))
                return objIn == null ? "" : objIn.ToString();
            return FindConver(tIn, tOut).ToConver(objIn);
        }
        private static IConverData FindConver(Type tIn, Type tOut)
        {
            string key =tIn.FullName+ tOut.FullName;
            IConverData conver;
            converCache.TryGetValue(key,out conver);
            if (conver == null)
            {
                conver = Activator.CreateInstance(typeof(DataConvertor<,>).MakeGenericType(tIn, tOut),tIn,tOut) as IConverData;
                converCache.Add(key, conver);
            }
            return conver;
        }
 
    }
}
